/**
 * Electron预加载脚本
 * 作为主进程和渲染进程之间的安全通信桥梁
 * 通过contextBridge API实现进程间安全通信，防止暴露敏感的Node.js API
 * 实现安全的IPC通信机制
 */
import { contextBridge, ipcRenderer, webUtils } from 'electron';

/**
 * IPC调用白名单通道定义
 * 严格控制渲染进程可调用的主进程API，增强应用安全性
 */
const ipcInvokeWhitelist = [
  'perform-calculation',      // 执行计算
  'open-file',               // 打开文件
  'save-file',               // 保存文件
  'ping',                    // 心跳测试
  'load-regulations',        // 加载规范文件列表
  'add-regulation',          // 添加规范文件
  'delete-regulation',       // 删除规范文件
  'open-regulation',         // 打开规范文件
  'save-regulation',         // 保存规范文件
  'batch-rename-files',      // 批量重命名文件
  'batch-rename-files-with-content', // 批量重命名文件（带内容）
  'scan-folder-files',       // 扫描文件夹文件
  'get-drag-drop-files'     // 获取拖放文件的完整路径
] as const;

/**
 * IPC发送白名单通道定义
 * 控制渲染进程可发送的事件类型
 */
const ipcSendWhitelist = [
  // 可以添加send类型的白名单通道
] as const;

/**
 * IPC接收白名单通道定义
 * 控制渲染进程可监听的事件类型
 */
const ipcReceiveWhitelist = [
  // 可以添加receive类型的白名单通道
] as const;

/**
 * IPC调用通道类型定义
 * 基于白名单数组生成类型，提供类型安全
 */
type IpcInvokeChannel = typeof ipcInvokeWhitelist[number];
type IpcSendChannel = typeof ipcSendWhitelist[number];
type IpcReceiveChannel = typeof ipcReceiveWhitelist[number];

/**
 * 安全的IPC调用辅助函数
 * 实现带错误处理的IPC通信
 * @template T 返回值类型
 * @param channel IPC通道名称
 * @param args 传递给IPC处理程序的参数
 * @returns IPC处理程序的返回值
 */
const safeInvoke = async <T>(channel: IpcInvokeChannel, ...args: any[]): Promise<T> => {
  try {
    return await (ipcRenderer.invoke(channel, ...args) as Promise<T>);
  } catch (error) {
    console.error(`IPC调用失败 channel="${channel}"`, error);
    throw error; // 重新抛出错误供调用者处理
  }
};

/**
 * 安全的IPC发送辅助函数
 * @param channel IPC通道名称
 * @param args 要发送的参数
 */
const safeSend = (channel: IpcSendChannel, ...args: any[]): void => {
  ipcRenderer.send(channel, ...args);
};

/**
 * 安全的IPC接收辅助函数
 * @param channel IPC通道名称
 * @param listener 事件监听器函数
 */
const safeReceive = (channel: IpcReceiveChannel, listener: (...args: any[]) => void): void => {
  ipcRenderer.on(channel, listener);
};

/**
 * 安全的IPC移除监听器辅助函数
 * @param channel IPC通道名称
 * @param listener 事件监听器函数
 */
const safeRemoveListener = (channel: IpcReceiveChannel, listener: (...args: any[]) => void): void => {
  ipcRenderer.off(channel, listener);
};

/**
 * 开发模式兼容处理
 * 优先使用contextBridge进行安全暴露
 * 开发环境下提供备选挂载方式
 */
if (typeof contextBridge !== 'undefined') {
  // 使用contextBridge安全暴露API给渲染进程
  contextBridge.exposeInMainWorld('electron', {
    ipc: {
      invoke: safeInvoke,  // 安全的IPC调用方法
      send: safeSend,      // 安全的IPC发送方法
      receive: safeReceive, // 安全的IPC接收方法
      removeListener: safeRemoveListener, // 安全的IPC移除监听器方法
      ping: () => safeInvoke('ping') // 便捷的ping方法
    },
    // 暴露webUtils.getPathForFile方法用于获取拖放文件的完整路径
    getPathForFile: (file: File) => webUtils.getPathForFile(file)
  });
} else {
  // 开发模式下的备选方案
  // 注意：此方式安全性较低，仅用于开发环境
  (window as any).electron = {
    ipc: {
      invoke: safeInvoke,
      send: safeSend,
      receive: safeReceive,
      removeListener: safeRemoveListener, // 安全的IPC移除监听器方法
      ping: () => safeInvoke('ping')
    },
    // 开发模式下也暴露getPathForFile方法
    getPathForFile: (file: File) => webUtils.getPathForFile(file)
  };
}
